// License: http://www.codeplex.com/entlibcontrib/Project/License.aspx
// Author: Randy

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Globalization;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using EntLibContrib.Logging.Configuration;

namespace EntLibContrib.Logging.Parser
{
    /// <summary>
    /// This class is responsibe for reading filtered LogEntry objects
    /// written with a time stamp function token with a custom date time format string
    /// from a normal text file which has previously
    /// been writtern by the Enterprise Library Logging Application Block. 
    /// </summary>
    public class TimeStampFunctionLogFileReader : CategoryLogFileReader
    {
        private readonly string completeTemplate;
        private readonly string logFileName;
        /// <summary>
        /// Uses the category configuration information and time stamp format provider
        /// to define the time stamp parser for log files.
        /// </summary>
        /// <param name="configurationFilepath">configuration file with the logging settings</param>
        /// <param name="categoryName">category name</param>
        /// <param name="formatProvider">time stamp format provider for month-day or day-month order, etc.</param>
        public TimeStampFunctionLogFileReader(string configurationFilepath, string categoryName, IFormatProvider formatProvider)
            : this(GetLoggingSettings(configurationFilepath), categoryName, formatProvider)
        {
            //LoggingSettings loggingSettings = GetLoggingSettings(configurationFilepath);
        }
        private TimeStampFunctionLogFileReader(LoggingSettings loggingSettings, string categoryName, IFormatProvider formatProvider)
            : this(loggingSettings, GetConfigTraceSourceData(loggingSettings, categoryName), formatProvider)
        {
            //TraceSourceData categoryTraceSourceData = GetConfigTraceSourceData(loggingSettings, categoryName);
        }
        private TimeStampFunctionLogFileReader(LoggingSettings loggingSettings, TraceSourceData categoryTraceSourceData, IFormatProvider formatProvider)
            : this(loggingSettings, GetFileTraceListener(loggingSettings, categoryTraceSourceData), formatProvider)
        {
            //IFileTraceListenerData fileTraceListenerData = GetFileTraceListener(loggingSettings, categoryTraceSourceData);
        }
        private TimeStampFunctionLogFileReader(LoggingSettings loggingSettings, IFileTraceListenerData fileTraceListenerData, IFormatProvider formatProvider)
            : this(fileTraceListenerData, GetTextFormatterData(loggingSettings, fileTraceListenerData), formatProvider)
        {
            //ITemplateTextFormatterData textFormatter = GetTextFormatterData(loggingSettings, fileTraceListenerData);
        }
        /// <summary>
        /// Constructor that specifies the configuration information needed
        /// to define the time stamp parser for log files.
        /// </summary>
        /// <param name="fileTraceListenerData">config data with the file name, header and footer</param>
        /// <param name="textFormatter">config data with the text formatter template</param>
        /// <param name="formatProvider">time stamp format provider for month-day or day-month order, etc.</param>
        public TimeStampFunctionLogFileReader(IFileTraceListenerData fileTraceListenerData, ITemplateText textFormatter, IFormatProvider formatProvider)
            : this(fileTraceListenerData, new TimeStampFunctionParser(textFormatter.Template, formatProvider))
        {
            //TimeStampFunctionParser functionParser = new TimeStampFunctionParser(textFormatter.Template, formatProvider);
        }
        private TimeStampFunctionLogFileReader(IFileTraceListenerData fileTraceListenerData, TimeStampFunctionParser functionParser)
            : base(functionParser.TimeStampParser)
        {
            if (fileTraceListenerData != null)
            {
                this.completeTemplate = RegularExpressionBuilder.ConcatCompleteTemplate(
                    fileTraceListenerData.Header,
                    functionParser.ParsingTemplate,
                    fileTraceListenerData.Footer);
                this.logFileName = fileTraceListenerData.FileName;
            }
            else
            {
                this.completeTemplate = RegularExpressionBuilder.ConcatCompleteTemplate(
                    string.Empty,
                    functionParser.ParsingTemplate,
                    string.Empty);
                this.logFileName = null;
            }
        }

        /// <summary>
        /// Log file name in the category configuration.
        /// </summary>
        public string LogFileName
        {
            get { return logFileName; }
        }

        /// <summary>
        /// Iterates through each log entry in the specified log file.
        /// </summary>
        /// <param name="logFileName">name of the log file to parse, or null to use the one specified in the configuration</param>
        /// <param name="filter">null for all or the filter range of interest</param>
        /// <returns>an enumerator that iterates through each log entry in the filter range</returns>
        public IEnumerable<LogEntry> ParseLogFile(string logFileName, Filter filter)
        {
            if (string.IsNullOrEmpty(logFileName))
                logFileName = this.logFileName;
            string logFileText = FileIO.ReadAllText(logFileName);
            foreach (LogEntry ent in ParseLogText(completeTemplate, logFileText, filter))
            {
                yield return ent;
            }
        }
        /// <summary>
        /// Iterates through each log entry that matches the template.
        /// </summary>
        /// <param name="logFileText">log file text</param>
        /// <param name="filter">null for all or the filter range of interest</param>
        /// <returns>an enumerator that iterates through each log entry in the filter range</returns>
        public IEnumerable<LogEntry> ParseLogText(string logFileText, Filter filter)
        {
            foreach (LogEntry ent in ParseLogText(completeTemplate, logFileText, filter))
            {
                yield return ent;
            }
        }
    }
}
